    /*
 * Copyright (c) 2022, yifengling0. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. No personal names or organizations' names associated with the
 *    Atomthreads project may be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#include <Arduino.h>
#include "atom.h"
#include "syslog.h"
#define ATOM_NONE_STANDARDIO
#include "drv_pwm.h"

#define PWM_RESOLUTION 8  // PWM 分辨率（8 位）

typedef struct pwm_channel {
	int gpio;
	int period;
	int pluse;
}pwm_channels;

static pwm_channels pwm_list[] = {
    {18, 0, 0}, {17, 0, 0}
};

static int pwm_ioctl(FD fd, int function, void* arg)
{
	int ret = OK;

	switch (function) {
	case IOCTL_PWM_SET:
	{
		PwmIoctlSet* set = (PwmIoctlSet*)arg;
		if (set->channel < ITEM_NUM(pwm_list)) {
				float period_sec = (float)set->period / 1e9;
				int frequency = 1 / period_sec;  
				// // 计算占空比（%）
				float duty_cycle_percent = ((float)set->pulse / (float)set->period) * 100;
				int duty_cycle = duty_cycle_percent * 255 / 100;  // 转换为 8 位范围内的值
				// // 配置并初始化指定的 PWM 通道
				ledcSetup(set->channel, frequency, PWM_RESOLUTION);
				// // 设置占空比
				ledcWrite(set->channel, duty_cycle);
				SYSLOG(LOG_DEBUG, "pwm %d, %d", frequency, duty_cycle );
		}
		else {
			ret = NG;
		}
	}
		break;
	case IOCTL_PWM_ENABLE:
	case IOCTL_PWM_DISABLE:
	{
		PwmIoctlState* state = (PwmIoctlState*)arg;
		if (state->channel < ITEM_NUM(pwm_list)) {
			if( state->enable ){
				// // 绑定 PWM 通道到指定 GPIO 引脚
				ledcAttachPin(pwm_list[state->channel].gpio, state->channel);
			}else{
				ledcDetachPin(pwm_list[state->channel].gpio);
			}
		}
		else {
			ret = NG;
		}
	}
	break;
	}

    return ret;
}

static Esp32Pwm _pwm;

void Esp32PwmCreate()
{
    PwmCreate(&_pwm.super, pwm_ioctl);
	SYSLOG(LOG_INFO, "pwm module initlized");
}
